/*-
 * FO.java      First octet of the SMS-SUBMIT/SMS-DELIVER
 *
 * $LastChangedBy: stein $
 * $LastChangedRevision: 95 $
 * $LastChangedDate: 2007-02-13 16:19:24 +0000 (Tue, 13 Feb 2007) $
 * $HeadURL: svn://localhost/SMS/src/com/googlecode/attention/sms/pdu/FO.java $
 *
 * Copyright (c) 2007, Stein Gunnar Bakkeby
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Stein Gunnar Bakkeby nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.googlecode.attention.sms.pdu;

import com.googlecode.attention.util.Convert;
import com.googlecode.attention.util.IntValue;

import static com.googlecode.attention.util.bit.ByteBitValues.*;

/**
 * First octet of the TPDU.
 *
 * <BR><A HREF="http://www.dreamfabric.com/sms/submit_fo.html">
 *              http://www.dreamfabric.com/sms/submit_fo.html</A>
 * <BR><A HREF="http://www.dreamfabric.com/sms/deliver_fo.html">
 *              http://www.dreamfabric.com/sms/deliver_fo.html</A>
 *
 * @author Stein Gunnar Bakkeby
 */
public class FO extends IntValue {
  
  /** Inherited constructor from IntValue. */
  public FO() {
    super(0);
  }
  
  /**
   * Inherited constructor from IntValue.
   * @param value The value of this object
   */
  public FO(final int value) {
    super(value);
  }
  
  /**
   * Inherited constructor from IntValue.
   * @param hex The value of this object in hex
   */
  public FO(final String hex) {
    super(hex);
  }
  
  /* SMS-DELIVER */ 
  /**
   * Constructor, used to create an SMS-DELIVER.
   * <BR>
   * <BR>Bit use in the first octet:
   * <BR>
   * <BR>bit7 - RP
   * <BR>bit6 - UDHI   (optional)
   * <BR>bit5 - SRI    (optional)
   * <BR>bit4 - Unused
   * <BR>bit3 - Unused
   * <BR>bit2 - MMS
   * <BR>bit1 - MTI
   * <BR>bit0 - MTI
   * <BR>
   * <BR>Unused bits will be set to '0'.
   * 
   * @param rp Reply-Path
   * @param udhi User-Data-Header-Indicator
   * @param sri Status-Report-Indicator
   * @param mms More-Messages-to-Send
   * @param mti Message-Type-Indicator
   */
  public FO(final RP rp,
            final UDHI udhi,
            final SRI sri,
            final MMS mms,
            final MTI mti) {
    value =   rp.value
          | udhi.value
          |  sri.value
          |  mms.value
          |  mti.value;
  }
  
  /**
   * Constructor, used to create an SMS-DELIVER
   * without the optional UDHI and SRI.
   * 
   * @param rp Reply-Path
   * @param mms More-Messages-to-Send
   * @param mti Message-Type-Indicator
   * @see #FO(RP, UDHI, SRI, MMS, MTI)
   */
  public FO(final RP rp, final MMS mms, final MTI mti) {
    value =  rp.value
          | mms.value
          | mti.value;
  }
  
  /* SMS-SUBMIT */
  /**
   * Constructor, used to create an SMS-SUBMIT.
   * <BR>
   * <BR>Bit use in the first octet:
   * <BR>
   * <BR>bit7 - RP
   * <BR>bit6 - UDHI   (optional)
   * <BR>bit5 - SRR    (optional)
   * <BR>bit4 - VPF
   * <BR>bit3 - VPF
   * <BR>bit2 - RD
   * <BR>bit1 - MTI
   * <BR>bit0 - MTI
   * 
   * @param rp Reply-Path
   * @param udhi User-Data-Header-Indicator
   * @param srr Status-Report-Request
   * @param vpf Validity-Period-Format
   * @param rd Reject-Duplicates
   * @param mti Message-Type-Indicator
   */ 
  public FO(final RP rp,
            final UDHI udhi,
            final SRR srr,
            final VPF vpf,
            final RD rd,
            final MTI mti) {
    value =   rp.value
          | udhi.value
          |  srr.value
          |  vpf.value
          |   rd.value
          |  mti.value;
  }
  
  /**
   * Constructor, used to create an SMS-SUBMIT
   * without the optional UDHI and SRR.
   * 
   * @param rp Reply-Path
   * @param vpf Validity-Period-Format
   * @param rd Reject-Duplicates
   * @param mti Message-Type-Indicator
   * @see #FO(RP, UDHI, SRR, VPF, RD, MTI)
   */
  public FO(final RP rp, final VPF vpf, final RD rd, final MTI mti) {
    value =  rp.value
          | vpf.value
          |  rd.value
          | mti.value;
  }
  
  /* SMS-COMMAND */
  /**
   * Constructor, used to create an SMS-COMMAND.
   * <BR>
   * <BR>Bit use in the first octet:
   * <BR>
   * <BR>bit7 - Unused
   * <BR>bit6 - UDHI   (optional)
   * <BR>bit5 - SRR    (optional)
   * <BR>bit4 - Unused
   * <BR>bit3 - Unused
   * <BR>bit2 - Unused
   * <BR>bit1 - MTI
   * <BR>bit0 - MTI
   * <BR>
   * <BR>Unused bits will be set to '0'.
   * 
   * @param udhi User-Data-Header-Indicator
   * @param srr Status-Report-Request
   * @param mti Message-Type-Indicator
   * @see #FO(MTI)
   */
  public FO(final UDHI udhi, final SRR srr, final MTI mti) {
    value = udhi.value
          |  srr.value
          |  mti.value;
  }
  
  /* SMS-COMMAND, SMS-DELIVER-REPORT, SMS-SUBMIT-REPORT */
  /**
   * Constructor, used to create an SMS-COMMAND, an SMS-DELIVER-REPORT,
   * or an SMS-SUBMIT-REPORT without the optional UDHI*.
   * <BR>
   * <BR>* and the optional SRR for SMS-COMMAND.
   * 
   * @param mti The message type indicator
   * @see #FO(UDHI, SRR, MTI)
   * @see #FO(UDHI, MTI)
   */
  public FO(final MTI mti) {
    value = mti.value;
  }
  
  /* SMS-DELIVER-REPORT, SMS-SUBMIT-REPORT */
  /**
   * Constructor, used to create an SMS-DELIVER-REPORT or an SMS-SUBMIT-REPORT.
   * <BR>
   * <BR>Bit use in the first octet:
   * <BR>
   * <BR>bit7 - Unused
   * <BR>bit6 - UDHI   (optional)
   * <BR>bit5 - Unused
   * <BR>bit4 - Unused
   * <BR>bit3 - Unused
   * <BR>bit2 - Unused
   * <BR>bit1 - MTI
   * <BR>bit0 - MTI
   * <BR>
   * <BR>Unused bits will be set to '0'.
   * 
   * @param udhi User-Data-Header-Indicator
   * @param mti Message-Type-Indicator
   */
  public FO(final UDHI udhi, final MTI mti) {
    value = udhi.value
          |  mti.value;
  }
  
  /* SMS-STATUS-REPORT */
  /**
   * Constructor, used to create an SMS-STATUS-REPORT.
   * <BR>
   * <BR>Bit use in the first octet:
   * <BR>
   * <BR>bit7 - Unused
   * <BR>bit6 - UDHI   (optional)
   * <BR>bit5 - SRQ
   * <BR>bit4 - Unused
   * <BR>bit3 - Unused
   * <BR>bit2 - MMS
   * <BR>bit1 - MTI
   * <BR>bit0 - MTI
   * <BR>
   * <BR>Unused bits will be set to '0'.
   * 
   * @param udhi User-Data-Header-Indicator
   * @param srq Status-Report-Qualifier
   * @param mms More-Messages-to-Send
   * @param mti Message-Type-Indicator
   * @see #FO(SRQ, MMS, MTI)
   */
  public FO(final UDHI udhi, final SRQ srq, final MMS mms, final MTI mti) {
    value = udhi.value
          |  srq.value
          |  mms.value
          |  mti.value;
  }
  
  /**
   * Constructor, used to create an SMS-STATUS-REPORT
   * without the optional UDHI.
   * 
   * @param srq Status-Report-Qualifier
   * @param mms More-Messages-to-Send
   * @param mti Message-Type-Indicator
   * @see #FO(UDHI, SRQ, MMS, MTI)
   */
  public FO(final SRQ srq, final MMS mms, final MTI mti) {
    value = srq.value
          | mms.value
          | mti.value;
  }
  
  /**
   * This will return the first octet.
   * 
   * @return The FO.
   */
  public String getHex() {
    return Convert.intToHex(value, 2);
  }
  
  /* Get method */
  /**
   * This will return the value of a the bits represented by
   * the static field values of this class.
   * 
   * @param type PDUElement values.
   * @see PDUElement
   * @return Logical and with FO value (value & type).
   */
  public int get(final PDUElement type) {
    return value & type.value;
  }
  
  /* Set methods */
  /**
   * This will set the value of the bits represented by
   * the static field values of this class.
   * 
   * @param type See static field values.
   * @param value The value to set the indicated type to.
   */
  public void set(final PDUElement type, final int value) {
    this.value &= (ALL ^ type.value); // keep all bits except those of this type
    /* The & type is to avoid illegal values for this type. */
    this.value |= (value & type.value);
  }
  
  /**
   * This will set the value of the bits represented by
   * the static field values of this class.
   * 
   * @param type See static field values.
   * @param value The value to set the indicated type to.
   */
  public void set(final PDUElement type, final boolean set) {
    if (set) {
      set(type);
    } else {
      unset(type);
    }
  }
  
  /**
   * This will set the value of the bits represented by
   * the static field values of this class.
   * 
   * @param type See static field values.
   * @param value The value to set the indicated type to.
   */
  public void set(final PDUElement type) {
    this.value &= (ALL ^ type.value); // keep all bits except those of this type
    this.value |= type.value;
  }
  
  /**
   * This will set the value of the bits represented by
   * the static field values of this class.
   * 
   * @param type See static field values.
   * @param value The value to set the indicated type to.
   */
  public void unset(final PDUElement type) {
    this.value &= (ALL ^ type.value); // keep all bits except those of this type
  }
  
  /**
   * This will set the value of the FO.
   * 
   * @param value Integer in range 0 - 255, will be masked by 0xFF.
   */
  public void setValue(final int value) {
    this.value = value & ALL;
  }
}